{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Deep Learning Models -- A collection of various deep learning architectures, models, and tips for TensorFlow and PyTorch in Jupyter Notebooks.\n",
    "- Author: Sebastian Raschka\n",
    "- GitHub Repository: https://github.com/rasbt/deeplearning-models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sebastian Raschka \n",
      "\n",
      "CPython 3.7.3\n",
      "IPython 7.6.1\n",
      "\n",
      "tensorflow 1.13.1\n"
     ]
    }
   ],
   "source": [
    "%load_ext watermark\n",
    "%watermark -a 'Sebastian Raschka' -v -p tensorflow"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Convolutional General Adversarial Networks with Label Smoothing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Same as [./gan-conv.ipynb](./gan-conv.ipynb) but with **label smoothing**.\n",
    "\n",
    "Here, the label smoothing approach is to replace real image labels (1's) by 0.9, based on the idea in\n",
    "\n",
    "- Salimans, Tim, Ian Goodfellow, Wojciech Zaremba, Vicki Cheung, Alec Radford, and Xi Chen. \"Improved techniques for training GANs.\" In Advances in Neural Information Processing Systems, pp. 2234-2242. 2016.\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'/device:GPU:0'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "import pickle as pkl\n",
    "\n",
    "tf.test.gpu_device_name()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From <ipython-input-3-05c8e8f3b1eb>:17: read_data_sets (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use alternatives such as official/mnist/dataset.py from tensorflow/models.\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/contrib/learn/python/learn/datasets/mnist.py:260: maybe_download (from tensorflow.contrib.learn.python.learn.datasets.base) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please write your own downloading logic.\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/contrib/learn/python/learn/datasets/mnist.py:262: extract_images (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tf.data to implement this functionality.\n",
      "Extracting MNIST_data/train-images-idx3-ubyte.gz\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/contrib/learn/python/learn/datasets/mnist.py:267: extract_labels (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tf.data to implement this functionality.\n",
      "Extracting MNIST_data/train-labels-idx1-ubyte.gz\n",
      "Extracting MNIST_data/t10k-images-idx3-ubyte.gz\n",
      "Extracting MNIST_data/t10k-labels-idx1-ubyte.gz\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/contrib/learn/python/learn/datasets/mnist.py:290: DataSet.__init__ (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use alternatives such as official/mnist/dataset.py from tensorflow/models.\n",
      "WARNING:tensorflow:From <ipython-input-3-05c8e8f3b1eb>:64: dense (from tensorflow.python.layers.core) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.dense instead.\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/python/framework/op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Colocations handled automatically by placer.\n",
      "WARNING:tensorflow:From <ipython-input-3-05c8e8f3b1eb>:65: batch_normalization (from tensorflow.python.layers.normalization) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.batch_normalization instead.\n",
      "WARNING:tensorflow:From <ipython-input-3-05c8e8f3b1eb>:74: conv2d_transpose (from tensorflow.python.layers.convolutional) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.conv2d_transpose instead.\n",
      "WARNING:tensorflow:From <ipython-input-3-05c8e8f3b1eb>:77: dropout (from tensorflow.python.layers.core) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.dropout instead.\n",
      "WARNING:tensorflow:From <ipython-input-3-05c8e8f3b1eb>:121: conv2d (from tensorflow.python.layers.convolutional) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use keras.layers.conv2d instead.\n",
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/python/ops/math_ops.py:3066: to_int32 (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use tf.cast instead.\n"
     ]
    }
   ],
   "source": [
    "### Abbreviatiuons\n",
    "# dis_*: discriminator network\n",
    "# gen_*: generator network\n",
    "\n",
    "########################\n",
    "### Helper functions\n",
    "########################\n",
    "\n",
    "def leaky_relu(x, alpha=0.0001):\n",
    "    return tf.maximum(alpha * x, x)\n",
    "\n",
    "\n",
    "########################\n",
    "### DATASET\n",
    "########################\n",
    "\n",
    "mnist = input_data.read_data_sets('MNIST_data')\n",
    "\n",
    "\n",
    "#########################\n",
    "### SETTINGS\n",
    "#########################\n",
    "\n",
    "# Hyperparameters\n",
    "learning_rate = 0.001\n",
    "training_epochs = 50\n",
    "batch_size = 64\n",
    "dropout_rate = 0.5\n",
    "\n",
    "# Architecture\n",
    "dis_input_size = 784\n",
    "gen_input_size = 100\n",
    "\n",
    "# Other settings\n",
    "print_interval = 200\n",
    "\n",
    "#########################\n",
    "### GRAPH DEFINITION\n",
    "#########################\n",
    "\n",
    "g = tf.Graph()\n",
    "with g.as_default():\n",
    "    \n",
    "    # Placeholders for settings\n",
    "    dropout = tf.placeholder(tf.float32, shape=None, name='dropout')\n",
    "    is_training = tf.placeholder(tf.bool, shape=None, name='is_training')\n",
    "    \n",
    "    # Input data\n",
    "    dis_x = tf.placeholder(tf.float32, shape=[None, dis_input_size],\n",
    "                           name='discriminator_inputs')     \n",
    "    gen_x = tf.placeholder(tf.float32, [None, gen_input_size],\n",
    "                           name='generator_inputs')\n",
    "\n",
    "\n",
    "    ##################\n",
    "    # Generator Model\n",
    "    ##################\n",
    "\n",
    "    with tf.variable_scope('generator'):\n",
    "        \n",
    "        # 100 => 784 => 7x7x64\n",
    "        gen_fc = tf.layers.dense(inputs=gen_x, units=3136,\n",
    "                                 bias_initializer=None, # no bias required when using batch_norm\n",
    "                                 activation=None)\n",
    "        gen_fc = tf.layers.batch_normalization(gen_fc, training=is_training)\n",
    "        gen_fc = leaky_relu(gen_fc)\n",
    "        gen_fc = tf.reshape(gen_fc, (-1, 7, 7, 64))\n",
    "        \n",
    "        # 7x7x64 => 14x14x32\n",
    "        deconv1 = tf.layers.conv2d_transpose(gen_fc, filters=32, \n",
    "                                             kernel_size=(3, 3), strides=(2, 2), \n",
    "                                             padding='same',\n",
    "                                             bias_initializer=None,\n",
    "                                             activation=None)\n",
    "        deconv1 = tf.layers.batch_normalization(deconv1, training=is_training)\n",
    "        deconv1 = leaky_relu(deconv1)     \n",
    "        deconv1 = tf.layers.dropout(deconv1, rate=dropout_rate)\n",
    "        \n",
    "        # 14x14x32 => 28x28x16\n",
    "        deconv2 = tf.layers.conv2d_transpose(deconv1, filters=16, \n",
    "                                             kernel_size=(3, 3), strides=(2, 2), \n",
    "                                             padding='same',\n",
    "                                             bias_initializer=None,\n",
    "                                             activation=None)\n",
    "        deconv2 = tf.layers.batch_normalization(deconv2, training=is_training)\n",
    "        deconv2 = leaky_relu(deconv2)     \n",
    "        deconv2 = tf.layers.dropout(deconv2, rate=dropout_rate)\n",
    "        \n",
    "        # 28x28x16 => 28x28x8\n",
    "        deconv3 = tf.layers.conv2d_transpose(deconv2, filters=8, \n",
    "                                             kernel_size=(3, 3), strides=(1, 1), \n",
    "                                             padding='same',\n",
    "                                             bias_initializer=None,\n",
    "                                             activation=None)\n",
    "        deconv3 = tf.layers.batch_normalization(deconv3, training=is_training)\n",
    "        deconv3 = leaky_relu(deconv3)     \n",
    "        deconv3 = tf.layers.dropout(deconv3, rate=dropout_rate)\n",
    "        \n",
    "        # 28x28x8 => 28x28x1\n",
    "        gen_logits = tf.layers.conv2d_transpose(deconv3, filters=1, \n",
    "                                                kernel_size=(3, 3), strides=(1, 1), \n",
    "                                                padding='same',\n",
    "                                                bias_initializer=None,\n",
    "                                                activation=None)\n",
    "        gen_out = tf.tanh(gen_logits, 'generator_outputs')\n",
    "\n",
    "\n",
    "    ######################\n",
    "    # Discriminator Model\n",
    "    ######################\n",
    "    \n",
    "    def build_discriminator_graph(input_x, reuse=None):\n",
    "\n",
    "        with tf.variable_scope('discriminator', reuse=reuse):\n",
    "            \n",
    "            # 28x28x1 => 14x14x8\n",
    "            conv_input = tf.reshape(input_x, (-1, 28, 28, 1))\n",
    "            conv1 = tf.layers.conv2d(conv_input, filters=8, kernel_size=(3, 3),\n",
    "                                     strides=(2, 2), padding='same',\n",
    "                                     bias_initializer=None,\n",
    "                                     activation=None)\n",
    "            conv1 = tf.layers.batch_normalization(conv1, training=is_training)\n",
    "            conv1 = leaky_relu(conv1)\n",
    "            conv1 = tf.layers.dropout(conv1, rate=dropout_rate)\n",
    "            \n",
    "            # 14x14x8 => 7x7x32\n",
    "            conv2 = tf.layers.conv2d(conv1, filters=32, kernel_size=(3, 3),\n",
    "                                     strides=(2, 2), padding='same',\n",
    "                                     bias_initializer=None,\n",
    "                                     activation=None)\n",
    "            conv2 = tf.layers.batch_normalization(conv2, training=is_training)\n",
    "            conv2 = leaky_relu(conv2)\n",
    "            conv2 = tf.layers.dropout(conv2, rate=dropout_rate)\n",
    "\n",
    "            # fully connected layer\n",
    "            fc_input = tf.reshape(conv2, (-1, 7*7*32))\n",
    "            logits = tf.layers.dense(inputs=fc_input, units=1, activation=None)\n",
    "            out = tf.sigmoid(logits)\n",
    "            \n",
    "        return logits, out    \n",
    "\n",
    "    # Create a discriminator for real data and a discriminator for fake data\n",
    "    dis_real_logits, dis_real_out = build_discriminator_graph(dis_x, reuse=False)\n",
    "    dis_fake_logits, dis_fake_out = build_discriminator_graph(gen_out, reuse=True)\n",
    "\n",
    "\n",
    "    #####################################\n",
    "    # Generator and Discriminator Losses\n",
    "    #####################################\n",
    "    \n",
    "    # Two discriminator cost components: loss on real data + loss on fake data\n",
    "    # Real data has class label 1, fake data has class label 0\n",
    "    dis_real_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=dis_real_logits, \n",
    "                                                            labels=tf.ones_like(dis_real_logits) * 0.9)\n",
    "    dis_fake_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=dis_fake_logits, \n",
    "                                                            labels=tf.zeros_like(dis_fake_logits))\n",
    "    dis_cost = tf.add(tf.reduce_mean(dis_fake_loss), \n",
    "                      tf.reduce_mean(dis_real_loss), \n",
    "                      name='discriminator_cost')\n",
    " \n",
    "    # Generator cost: difference between dis. prediction and label \"1\" for real images\n",
    "    gen_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=dis_fake_logits,\n",
    "                                                       labels=tf.ones_like(dis_fake_logits) * 0.9)\n",
    "    gen_cost = tf.reduce_mean(gen_loss, name='generator_cost')\n",
    "    \n",
    "    \n",
    "    #########################################\n",
    "    # Generator and Discriminator Optimizers\n",
    "    #########################################\n",
    "      \n",
    "    dis_optimizer = tf.train.AdamOptimizer(learning_rate)\n",
    "    dis_train_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='discriminator')\n",
    "    dis_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope='discriminator')\n",
    "    \n",
    "    with tf.control_dependencies(dis_update_ops): # required to upd. batch_norm params\n",
    "        dis_train = dis_optimizer.minimize(dis_cost, var_list=dis_train_vars,\n",
    "                                           name='train_discriminator')\n",
    "    \n",
    "    gen_optimizer = tf.train.AdamOptimizer(learning_rate)\n",
    "    gen_train_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='generator')\n",
    "    gen_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope='generator')\n",
    "    \n",
    "    with tf.control_dependencies(gen_update_ops): # required to upd. batch_norm params\n",
    "        gen_train = gen_optimizer.minimize(gen_cost, var_list=gen_train_vars,\n",
    "                                           name='train_generator')\n",
    "    \n",
    "    # Saver to save session for reuse\n",
    "    saver = tf.train.Saver()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Minibatch: 0001 | Dis/Gen Cost:    1.290/1.057\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.054/1.374\n",
      "Minibatch: 0401 | Dis/Gen Cost:    0.993/1.822\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.580/2.214\n",
      "Minibatch: 0801 | Dis/Gen Cost:    0.708/1.710\n",
      "Epoch:     0001 | Dis/Gen AvgCost: 0.821/1.891\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.013/2.102\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.113/1.212\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.247/1.045\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.935/1.376\n",
      "Minibatch: 0801 | Dis/Gen Cost:    0.685/2.113\n",
      "Epoch:     0002 | Dis/Gen AvgCost: 0.884/1.699\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.089/1.191\n",
      "Minibatch: 0201 | Dis/Gen Cost:    0.971/1.760\n",
      "Minibatch: 0401 | Dis/Gen Cost:    0.769/2.239\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.275/1.442\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.023/1.846\n",
      "Epoch:     0003 | Dis/Gen AvgCost: 0.996/1.580\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.088/1.628\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.095/1.451\n",
      "Minibatch: 0401 | Dis/Gen Cost:    0.891/1.560\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.974/1.353\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.140/1.344\n",
      "Epoch:     0004 | Dis/Gen AvgCost: 1.119/1.341\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.197/1.256\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.281/1.192\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.159/1.402\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.397/0.997\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.230/1.087\n",
      "Epoch:     0005 | Dis/Gen AvgCost: 1.177/1.229\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.104/1.103\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.385/1.217\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.069/1.247\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.126/1.309\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.202/1.529\n",
      "Epoch:     0006 | Dis/Gen AvgCost: 1.257/1.143\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.274/1.314\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.362/0.915\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.395/1.082\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.270/0.947\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.327/1.151\n",
      "Epoch:     0007 | Dis/Gen AvgCost: 1.324/1.042\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.417/0.794\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.210/0.995\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.558/0.925\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.191/1.106\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.150/1.047\n",
      "Epoch:     0008 | Dis/Gen AvgCost: 1.306/1.026\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.186/0.991\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.332/1.005\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.185/1.090\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.314/1.000\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.115/1.158\n",
      "Epoch:     0009 | Dis/Gen AvgCost: 1.305/1.006\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.348/0.868\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.367/0.863\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.328/1.020\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.395/0.962\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.390/0.979\n",
      "Epoch:     0010 | Dis/Gen AvgCost: 1.300/1.025\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.403/1.199\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.222/0.985\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.212/1.235\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.052/1.168\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.268/0.917\n",
      "Epoch:     0011 | Dis/Gen AvgCost: 1.305/1.002\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.304/0.949\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.198/1.137\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.237/1.077\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.337/0.930\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.341/0.909\n",
      "Epoch:     0012 | Dis/Gen AvgCost: 1.315/0.986\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.411/0.964\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.335/0.955\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.319/0.927\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.257/0.952\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.283/0.973\n",
      "Epoch:     0013 | Dis/Gen AvgCost: 1.329/0.974\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.266/1.170\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.478/0.830\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.300/0.954\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.305/0.980\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.435/0.809\n",
      "Epoch:     0014 | Dis/Gen AvgCost: 1.325/0.946\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.305/0.940\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.473/0.910\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.408/0.976\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.312/0.944\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.412/0.905\n",
      "Epoch:     0015 | Dis/Gen AvgCost: 1.338/0.949\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.297/0.971\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.196/1.051\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.262/0.956\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.248/0.974\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.278/0.954\n",
      "Epoch:     0016 | Dis/Gen AvgCost: 1.331/0.947\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.227/0.928\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.304/0.998\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.195/0.963\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.230/0.910\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.281/1.064\n",
      "Epoch:     0017 | Dis/Gen AvgCost: 1.335/0.914\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.423/0.921\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.309/0.892\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.311/0.895\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.378/0.842\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.388/0.833\n",
      "Epoch:     0018 | Dis/Gen AvgCost: 1.344/0.902\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.177/1.030\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.255/1.045\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.359/0.986\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.273/0.944\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.297/0.914\n",
      "Epoch:     0019 | Dis/Gen AvgCost: 1.333/0.928\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.403/0.921\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.272/0.932\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.250/0.931\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.298/0.904\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.290/0.852\n",
      "Epoch:     0020 | Dis/Gen AvgCost: 1.332/0.916\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.384/0.898\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.386/0.886\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.314/1.025\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.546/0.881\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.202/1.017\n",
      "Epoch:     0021 | Dis/Gen AvgCost: 1.330/0.930\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.232/1.135\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.317/0.930\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.194/1.068\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.378/0.859\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.267/0.955\n",
      "Epoch:     0022 | Dis/Gen AvgCost: 1.339/0.907\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.294/0.937\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.347/0.860\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.362/0.878\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.228/0.866\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.344/0.900\n",
      "Epoch:     0023 | Dis/Gen AvgCost: 1.339/0.895\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.454/0.811\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.448/0.924\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.300/0.950\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.326/0.881\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.283/1.006\n",
      "Epoch:     0024 | Dis/Gen AvgCost: 1.340/0.889\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.348/0.922\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.430/0.758\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.369/0.870\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.343/0.838\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.189/0.967\n",
      "Epoch:     0025 | Dis/Gen AvgCost: 1.347/0.891\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.395/0.865\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.495/0.803\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.450/0.861\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.299/0.953\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.426/0.793\n",
      "Epoch:     0026 | Dis/Gen AvgCost: 1.339/0.891\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.348/0.856\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.303/0.942\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.344/0.846\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.276/0.888\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.393/0.855\n",
      "Epoch:     0027 | Dis/Gen AvgCost: 1.347/0.881\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.305/0.963\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.391/0.850\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.380/0.795\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.295/0.840\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.194/0.927\n",
      "Epoch:     0028 | Dis/Gen AvgCost: 1.350/0.867\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.394/0.805\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.288/0.889\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.331/0.922\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.466/0.795\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.430/0.779\n",
      "Epoch:     0029 | Dis/Gen AvgCost: 1.341/0.873\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.297/0.879\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.268/0.932\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.432/0.831\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.335/0.845\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.401/0.962\n",
      "Epoch:     0030 | Dis/Gen AvgCost: 1.337/0.872\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.300/0.910\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.369/0.872\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.421/0.826\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.351/0.946\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.401/0.864\n",
      "Epoch:     0031 | Dis/Gen AvgCost: 1.344/0.863\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.273/0.875\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.353/0.836\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.372/0.867\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.368/0.853\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.186/0.904\n",
      "Epoch:     0032 | Dis/Gen AvgCost: 1.342/0.868\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.405/0.823\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.321/0.931\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.361/0.858\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.274/0.891\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.397/0.848\n",
      "Epoch:     0033 | Dis/Gen AvgCost: 1.345/0.858\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.174/0.992\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.278/0.902\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.341/0.900\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.267/0.906\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.369/0.820\n",
      "Epoch:     0034 | Dis/Gen AvgCost: 1.346/0.862\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.305/0.838\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.403/0.846\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.338/0.850\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.343/0.833\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.334/0.797\n",
      "Epoch:     0035 | Dis/Gen AvgCost: 1.353/0.850\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.394/0.846\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.407/0.841\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.481/0.732\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.328/0.884\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.414/0.789\n",
      "Epoch:     0036 | Dis/Gen AvgCost: 1.352/0.850\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.310/0.838\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.376/0.805\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.341/0.864\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.328/0.896\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.383/0.791\n",
      "Epoch:     0037 | Dis/Gen AvgCost: 1.352/0.840\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.295/0.861\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.455/0.826\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.420/0.796\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.337/0.871\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.328/0.863\n",
      "Epoch:     0038 | Dis/Gen AvgCost: 1.348/0.852\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.382/0.824\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.302/0.897\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.385/0.792\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.314/0.847\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.423/0.779\n",
      "Epoch:     0039 | Dis/Gen AvgCost: 1.350/0.848\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.419/0.852\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.390/0.885\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.348/0.802\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.349/0.833\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.382/0.775\n",
      "Epoch:     0040 | Dis/Gen AvgCost: 1.349/0.842\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.289/0.918\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.410/0.772\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.393/0.790\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.317/0.829\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.267/0.878\n",
      "Epoch:     0041 | Dis/Gen AvgCost: 1.358/0.837\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.342/0.859\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.340/0.870\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.394/0.803\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.355/0.820\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.359/0.836\n",
      "Epoch:     0042 | Dis/Gen AvgCost: 1.348/0.847\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.330/0.807\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.386/0.836\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.400/0.816\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.355/0.855\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.315/0.919\n",
      "Epoch:     0043 | Dis/Gen AvgCost: 1.354/0.845\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.338/0.838\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.317/0.866\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.341/0.819\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.260/0.863\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.285/0.917\n",
      "Epoch:     0044 | Dis/Gen AvgCost: 1.351/0.850\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.378/0.826\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.332/0.881\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.247/0.920\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.339/0.807\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.350/0.850\n",
      "Epoch:     0045 | Dis/Gen AvgCost: 1.356/0.836\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.341/0.872\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.406/0.818\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.478/0.765\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.426/0.837\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.271/0.824\n",
      "Epoch:     0046 | Dis/Gen AvgCost: 1.356/0.832\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.388/0.812\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.279/0.916\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.331/0.805\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.321/0.861\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.344/0.860\n",
      "Epoch:     0047 | Dis/Gen AvgCost: 1.351/0.843\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.342/0.807\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.356/0.813\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.361/0.806\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.393/0.811\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.379/0.783\n",
      "Epoch:     0048 | Dis/Gen AvgCost: 1.357/0.824\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.368/0.793\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.364/0.812\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.339/0.843\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.331/0.798\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.358/0.815\n",
      "Epoch:     0049 | Dis/Gen AvgCost: 1.359/0.823\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.367/0.819\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.300/0.845\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.364/0.808\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.284/0.912\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.334/0.837\n",
      "Epoch:     0050 | Dis/Gen AvgCost: 1.355/0.833\n"
     ]
    }
   ],
   "source": [
    "##########################\n",
    "### TRAINING & EVALUATION\n",
    "##########################\n",
    "\n",
    "with tf.Session(graph=g) as sess:\n",
    "    sess.run(tf.global_variables_initializer())\n",
    "    \n",
    "    avg_costs = {'discriminator': [], 'generator': []}\n",
    "\n",
    "    for epoch in range(training_epochs):\n",
    "        dis_avg_cost, gen_avg_cost = 0., 0.\n",
    "        total_batch = mnist.train.num_examples // batch_size\n",
    "\n",
    "        for i in range(total_batch):\n",
    "            \n",
    "            batch_x, batch_y = mnist.train.next_batch(batch_size)\n",
    "            batch_x = batch_x*2 - 1 # normalize\n",
    "            batch_randsample = np.random.uniform(-1, 1, size=(batch_size, gen_input_size))\n",
    "            \n",
    "            # Train\n",
    "            \n",
    "            _, dc = sess.run(['train_discriminator', 'discriminator_cost:0'],\n",
    "                             feed_dict={'discriminator_inputs:0': batch_x, \n",
    "                                        'generator_inputs:0': batch_randsample,\n",
    "                                        'dropout:0': dropout_rate,\n",
    "                                        'is_training:0': True})\n",
    "            \n",
    "            _, gc = sess.run(['train_generator', 'generator_cost:0'],\n",
    "                             feed_dict={'generator_inputs:0': batch_randsample,\n",
    "                                        'dropout:0': dropout_rate,\n",
    "                                        'is_training:0': True})\n",
    "            \n",
    "            dis_avg_cost += dc\n",
    "            gen_avg_cost += gc\n",
    "\n",
    "            if not i % print_interval:\n",
    "                print(\"Minibatch: %04d | Dis/Gen Cost:    %.3f/%.3f\" % (i + 1, dc, gc))\n",
    "                \n",
    "\n",
    "        print(\"Epoch:     %04d | Dis/Gen AvgCost: %.3f/%.3f\" % \n",
    "              (epoch + 1, dis_avg_cost / total_batch, gen_avg_cost / total_batch))\n",
    "        \n",
    "        avg_costs['discriminator'].append(dis_avg_cost / total_batch)\n",
    "        avg_costs['generator'].append(gen_avg_cost / total_batch)\n",
    "    \n",
    "    \n",
    "    saver.save(sess, save_path='./gan-conv.ckpt')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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Kb964IEHaGhoCHQZPdJloBtj1gMVna0CxIm9bjfWt27/DD0ZMhEqDkJLfb/sTik1+J2cUrcjPQl0f01/21v+6EP/HTAeOAZ8DHzHGNPuT0tEVohIvojkl5aW9n7P6RMAoze7UCoI/PznP2fcuHFcdtllLF++nPvvv5/9+/ezePFiZsyYwZw5c9quruxoSluA++67j5kzZzJlyhTuvPNOgHan1L311lvJy8tj4sSJbev99re/5dixYyxYsIAFCxYAsGrVKiZPnsykSZO4/fbb2/YTGxvLT37yEy688ELee++9/voxdcofl/5fAWwDLgXOA94UkQ3GmLMmVTDGrARWgr1StNd7PnUKgBEzOl9XKdU9r98BJz727zaHToYrO74DUH5+Ps8999xZ0+euWLGChx56iNzcXN5//32+8Y1vtE3K1d6UtqtXr6agoIDNmzdjjGHp0qWsX7+eUaNGnTWl7t13301ycjIej4eFCxfy0Ucfcdttt/HrX/+adevWkZqayrFjx7j99tvZunUrSUlJXH755bz44otcc8011NfXM2nSJO666y7//qx6wR+B/mXgHmPnENgnIgeBccBmP2y7c0lZ4IzSfnSlBrmNGzeybNkyoqKiALj66qtpampi06ZNXH/99W3rNTc3t33d3pS2q1evZvXq1Zx//vmAndSroKCAUaNGnTWl7tNPP83KlStxu90cP36cXbt2MWXKlNPq2rJlC/PnzyctLQ2w87esX7+ea665BofDwWc/+9m++YH0kD8C/TCwENggIkOAscABP2y3a2EOSB+nI12U8qdOWtJ9pb05pbxeL4mJiW0zK56pvSltjTH88Ic/5Gtf+9pp6xYWFp42Ve3Bgwe5//772bJlC0lJSdx8883nPPWty+XC4XB0fmD9rDvDFlcB7wFjRaRIRL4iIl8Xka/7Vvk5MFtEPgbWALcbY8r6ruQzpE+Ekt39tjullP9dcsklvPLKKzQ1NVFXV8err75KdHQ02dnZPPPMM4AN1+3bt3e6nSuuuIJHHnmEuro6AI4ePUpJSclZ69XU1BATE0NCQgLFxcW8/vrrbctOnf72wgsv5J133qGsrAyPx8OqVauYN2+evw7b77psoRtjlnex/Bhwud8qOlfp42Hb/0J9GcSkBqwMpVTPzZw5k6VLlzJ16lQyMzPJy8sjISGBxx9/nFtvvZVf/OIX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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.plot(range(len(avg_costs['discriminator'])), \n",
    "         avg_costs['discriminator'], label='discriminator')\n",
    "plt.plot(range(len(avg_costs['generator'])),\n",
    "         avg_costs['generator'], label='generator')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /home/raschka/miniconda3/lib/python3.7/site-packages/tensorflow/python/training/saver.py:1266: checkpoint_exists (from tensorflow.python.training.checkpoint_management) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Use standard file APIs to check for files with this prefix.\n",
      "INFO:tensorflow:Restoring parameters from ./gan-conv.ckpt\n"
     ]
    },
    {
     "data": {
      "image/png": "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4osvjnnfitL05Iedsyt7jG699dZa1qULk1TJkpkSX375pZZ17NhRY/kckOUHgfAON3YqjnympHPHo1xgU82yJ7odJW3n+X/66acAwsd0586dNR4/fjyA3EkvW+zxEhEReZTwPN50iNIcx6iLwpy7QpKP83ijLleP8enTp2tsMwixBgnZzJfNiF133XUAgH/+858ZqGFsudreuSrlebxERESUHjzxEhEReZR7V6WJiLLIztfn2sWUDPZ4iYiIPOKJl4iIyCOeeImIiDziiZeIiMgjnniJiIg84omXiIjII554iYiIPPK6ZKRzbhWA9QBib8CY2+ohva+rRRAE9VN5gJL2XoT01y0KItfeQF4f45k4htJ1jOdjewMRPMb5mVIpcdvb64kXAJxzxelYEzdqovy6oly3ZEX5NUW5bsmK8muKct1SEeXXFeW6Jcvna2KqmYiIyCOeeImIiDzKxol3aBae04cov64o1y1ZUX5NUa5bsqL8mqJct1RE+XVFuW7J8vaavF/jJSIiKmRMNRMREXnEEy8REZFHPPESERF5xBMvERGRRzzxEhERecQTLxERkUc88RIREXmU0onXOXe4c26uc+5L59zAdFWKiIgoXyW9gIZzrgqAeQC6AlgKYAqAXkEQzE5f9YiIiPLL5in8bQcAXwZBsAAAnHPPA+gBIO6Jt169ekHLli1TeMrCMXXq1NWpbuHF9k5cOtobYJtXBo9xv9jefpXX3qmceJsAWGJ+Xwqg46Z3cs71A9APAJo3b47i4uIUnrJwOOcWJfl3bO8kJNveJX/LNk8Cj3G/2N5+ldfeqVzjdTHKyuStgyAYGgRBURAERfXrp9yhoAqwvf1jm/vF9vaL7Z1+qZx4lwJoZn5vCuCb1KpDRESU31I58U4B0Mo5t71zriqAEwG8np5qERER5aekr/EGQbDBOTcAwGgAVQAMD4JgVtpqRlQg/vrrL40324xT64nyXSqDqxAEwSgAo9JUFyIiorzHr9dEREQepdTjJdrUsGHDNH7hhRc0fvnllwEA1apV816nqGN6maiw8B1PRETkEU+8REREHjHVTJXy559/anzOOedo/OyzzwIA1q9fr2Vbb721xu+//z4A4Igjjsh0FYmoAJx11lkAgMmTJ2vZnDlzNLaXcH7//XcAwNKlS7WscePGma5iXOzxEhEReVSwPd41a9YAAFq0aFGmDACqVKnivU65oEuXLhpPnDhRY9nlqlmz0sXMrrvuOo333nvvzFeO0sruXPbLL78AAC677DItGzlypMbObVxBdpdddtGyd999N9NVzCsHHHCAxpMmTQIANG3aVMuWLFlS5m8KzaJFpcsfy/F5+umna9nrr5eu4fThhx+Wue8ff/yR4Romhj1eIiIij3jiJSIi8qigUs12aT5Jff70009aNm7cOI0PPfRQfxXLAZKqmTt3rpZJetHG33//vZZdddVVGstWYrfeequW1axZMzOVpUpbuHAhAGDs2LFaJnOvgdK0sQxS2dT2228PAPjvf/+bqSrmlQkTJgAIp0m//vrrMvezn0829W/fe4XEXhp8+OGHAYQ/188++2yN27dvr/GsWRtXM543b56WNW/ePGP1rAh7vERERB7xxEtERORRQaWae/XqpbGkdWzKxs47pTBpp3/9619aZlORMj/uxx9/1DI7p3fIkCEAStNDALDrrrtq/Omnn2q8+eYFdVh6NXPmTI27d++ucaw0Z0XsPO57770XAP93m9qwYYPGhxxyiMYffPBBmdtj+eGHHzT+9ttvNc7mHNSokM8kOwPFpuZXr16tsdzn559/9lS78rHHS0RE5FHefz2133DefvvtMrfbHm9U5nhF2Q033KDxoEGDNJZ2XLdunZbJgCoAOPPMMwGE5yLaVWbefPNNjbt16waAc6nTxWYe9thjD43tYB2xxRZbaFy3bl2NpXd77LHHapnNWBTqYJ9YfvvtN42nTZumsZ1XWlFPV7Rs2VLj2rVrp165PGc/X1q3bq2xtP1+++3nvU6xsMdLRETkEU+8REREHuV9qllSnACwdu3aMrfb1NpLL72kcefOnTWOtV/qihUrNP7uu+8AAG3atEmprrkmVirYzs09+OCDNZal3my6326YIJssAMD+++8PAKhXr176KluAPvnkEwDhQT128FOTJk00lpRmhw4dtOzqq6/WuHr16pmqZqTJUpkAcOKJJwIABg4cqGX77LOPxpJu33LLLbVMPhuA8AYjct+tttpKyy644AKNr7zySgDcvzoRNrX/yiuvaPzZZ59pLANn7f8mmyrs8TrnhjvnVjrnZpqyOs65Mc65+SU/efGBiIgoAYmkmh8HcPgmZQMBjAuCoBWAcSW/ExERUQUqTDUHQTDROddyk+IeADqXxE8AGA/g8jTW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1q9fP40la2MHadp9ueX92aZNGy0bMmSIxuzpJsdmDexaC7Khx6RJk7Rs0aJFGkuG0A6Sspvi2DnU2ezdxsIeLxERkUc88RIREXmU86lmigaZ+2j3R45yqieXvPTSSxrbeesy0KpTp05a9tZbb2nse+H3XGEvgdiYsq9u3boa2+Vn8w17vERERB7xxEtEROQRU82UFn/88QeA8A5SNu1Mybv66qtjxkSUm9jjJSIi8og9XkqLuXPnZrsKREQ5gT1eIiIij3jiJSIi8sj5XJjfObcKwHoAq709qT/1kN7X1SIIgvqpPEBJey9C+usWBZFrbyCvj/FMHEPpOsbzsb2BCB7j/EyplLjt7fXECwDOueIgCIq8PqkHUX5dUa5bsqL8mqJct2RF+TVFuW6piPLrinLdkuXzNTHVTERE5BFPvERERB5l48Q7NAvP6UOUX1eU65asKL+mKNctWVF+TVGuWyqi/LqiXLdkeXtN3q/xEhERFTKmmomIiDziiZeIiMgjnniJiIg84omXiIjII554iYiIPOKJl4iIyCOeeImIiDxK6cTrnDvcOTfXOfelc25guipFRESUr5JeQMM5VwXAPABdASwFMAVAryAIZqevekRERPll8xT+tgOAL4MgWAAAzrnnAfQAEPfEW69evaBly5YpPGXhmDp16upUt/BieycuHe0NsM0rg8e4X2xvv8pr71ROvE0ALDG/LwXQcdM7Oef6AegHAM2bN0dxcXEKT1k4nHOLkvw7tncSkm3vkr9lmyeBx7hfbG+/ymvvVK7xuhhlZfLWQRAMDYKgKAiCovr1U+5QUAXY3v6xzf1ie/vF9k6/VE68SwE0M783BfBNatUhIiLKb6mceKcAaOWc2945VxXAiQBeT0+1iIiI8lPS13iDINjgnBsAYDSAKgCGB0EwK201I6KsWrlypcbnnXceAKBp06ZadsEFF2jcrJlNfhFReVIZXIUgCEYBGJWmuhAREeU9rlxFRETkUUo9Xgr766+/NN5sM36nodz20ksvaTx9+nQApSlngOllomTx7EBEROQRT7xEREQeMdWcpJEjR2p81VVXAQDmz5+vZf/61780fuihh/xVjCgFX3/9tcYzZ87UeM6cOVmoTX7p3LmzxrL6008//ZSl2lA2scdLRETkEXu8lTBlyhSNBwwYoPG3334LAHCudBXNa665xl/FiBL02muvadyzZ0+NN2zYAAA48MADtey9997zV7E88uuvv2p82GGHaTxx4kSNt9hiCwCl7Q4Am2/Oj+NCwR4vERGRRzzxEhERecTcRgKWLVsGIDxIStLL1q677qpxkyZNMl8xokraeuutNf7jjz80rlmzJgBg9OjRWmYvnVDittpqK41/++23mPepU6cOAKBKlSpe6kTRwh4vERGRRzzxEhERecRUcxySXgaAZ599FgDw2GOPaZmMSgSABg0aACidz5uLZCSmTZNlwp9//qmxnSf65JNPajxr1sZNriQdBwBDhgzRWNKiVHmnnXaaxrZ9zz//fAAcWZsO9rieOnVqzPv07t0bQH6k89evX6/xjjvuWKa8du3aWnbyySdrfOihhwIAdthhBy0LgkDjxYsXAwAaNmyoZTY1P2nSJADhXbRWr16tcbdu3TSeNm0aAODcc8/Vsmy2PXu8REREHvHrbRw//vijxjfddBOA8DekFi1aaDx79mwA4V5wLrCbOnz44YcAgCVLlmjZkUceqbFs+mDbwM5XlG+iL7/8spbZlbzeeustAMDChQu1LN7AE2Gfy/bEhw0bVuZ2iu/jjz/WuHr16hrbTQ7OPPNMABzskw42k2Dn6dpj+Prrr/dap0zaZpttNJbMCQDcc889AEp7rgBw6623anz//fcDCGfBYn0m2A1n7Hte2taW2fveddddGksmp2/fvlqW6exeedjjJSIi8ognXiIiIo+YajZ+/vlnjeXCPwCsXbsWANChQwcts3uV5lqKWdi0jKSdBw8erGUXXHCBxj/88ENantMO3mnUqJHGNiUngzJs2sluSiEprBo1aqSlTvlKBqrMmzdPy+zgk0GDBmnctGlTfxXLU3K8FhUVxbx933331Tibac50s6negQMHanzJJZcAAL744gstO+mkkzSeMWNGmceyn6Vy2cNe0orFDsiyl88smbO+YMECLWvTpk25j5tJFfZ4nXPDnXMrnXMzTVkd59wY59z8kp+1y3sMIiIi2iiRVPPjAA7fpGwggHFBELQCMK7kdyIiIqpAhanmIAgmOudablLcA0DnkvgJAOMBXJ7GeiXFphySGfFq0xDLly/XWNKjdmcXmybNB126dAEA3HvvvVr2zTffaCxpmVq1ammZTQUvWrQIANC+ffuYj7/lllsCCKeUbarYLlV4wgknAAinjdatW6fxhAkTAADdu3cv/0UVOHkP2HmQ9pJBu3btvNcpn8klErk0tamnn37aZ3WyTj43d9ttNy376KOPNF6xYgUA4KuvvtKybbfdVmNZdrdq1apaZo9f2ctY9jYGgFdeeUXj8ePHayypZnt55cUXX6zMy0mrZAdXNQyCYDkAlPxsEO+Ozrl+zrli51zxqlWrknw6ShTb2z+2uV9sb7/Y3umX8cFVQRAMBTAUAIqKioIK7l5p9tul3e/ylltuAQC8++67WhZrQIO9cG9XNbG9rVNOOQVAbvRyk21v6R3ZQWWVsfvuuyf1d8L2vuygL2GzGTK4ys4zzub800wf48n65ZdfAJQev5tK14A536LU3jaDI4OI7CBNy25KkUvS2d62R/u3v/0t9DMRjRs3LlNms2xnn322xo8//rjGMk/dzilONUOaimR7vCucc40BoOTnygruT0REREj+xPs6gN4lcW8Ar5VzXyIiIipRYarZOfccNg6kquecWwpgEIDBAEY45/oAWAygZyYrWR6bYrQLwO+8885lbo9FlnsEwqnqTp06afzggw+mXE8q33bbbadxv379AAB33313zPu2atUKAJeMrIhcRrEpZdtme+21l/c65Rs7L10GGNoUpmUHJlJm2OP7jDPO0Pjhhx8GEN7EIZsSGdXcK85NXdJcFyIiorzHJSOJiIg8yvklI21KeM2aNRrLnpjxUs0yajne8m52NHSuLgmZqypKIctuKLFGPxc6mRsJlO75akfetm7dWuN8WrYwWz777DONL7744jK3288OmctO/smewHZ9hmziJxcREZFHOd/jtfOyLFkt5bvvvtMyuxepXHi3AyFatmypMXu52bNs2bIyZbZ3e/TRR/usTk6ZNWuWxmPGjAEQbrvDDy9d/ZWD01I3ffp0jWP1puyqTcww+GU/+99//30ApfN5gewe/+zxEhERecQTLxERkUc5n2ru3Lmzxnah/ZtuuglAeKH/L7/8UuMRI0YAAJo3b65lCxcuzFQ1qQL2f/Pmm2+Wud0uFXfAAQd4qVOusEsRHnXUURrLAEI7f/TOO+/0V7E81a1bN41jHavWAw88kOnqUBzvvPOOxrKBRVSW/WWPl4iIyCOeeImIiDzK+VTzyJEjNbY7Ckn85JNPatn555+vsYz0nD9/fqarSAmwu0RJWsiOOrz22ms1zuZORImQkfLZGDVpR+NLmw4b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\n",
      "text/plain": [
       "<Figure size 576x576 with 25 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "####################################\n",
    "### RELOAD & GENERATE SAMPLE IMAGES\n",
    "####################################\n",
    "\n",
    "\n",
    "n_examples = 25\n",
    "\n",
    "with tf.Session(graph=g) as sess:\n",
    "    saver.restore(sess, save_path='./gan-conv.ckpt')\n",
    "\n",
    "    batch_randsample = np.random.uniform(-1, 1, size=(n_examples, gen_input_size))\n",
    "    new_examples = sess.run('generator/generator_outputs:0',\n",
    "                            feed_dict={'generator_inputs:0': batch_randsample,\n",
    "                                       'dropout:0': 0.0,\n",
    "                                       'is_training:0': False})\n",
    "\n",
    "fig, axes = plt.subplots(nrows=5, ncols=5, figsize=(8, 8),\n",
    "                         sharey=True, sharex=True)\n",
    "\n",
    "for image, ax in zip(new_examples, axes.flatten()):\n",
    "    ax.imshow(image.reshape((dis_input_size // 28, dis_input_size // 28)), cmap='binary')\n",
    "\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
